﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Psm.PubSub.Messaging;
using System.Diagnostics;
using Psm.PubSub.Serialization;
using Psm.PubSub.Serialization.Prefixed;
using Psm.Util;
using Psm.Container;
using Psm.PubSub.StateCache;

namespace PubSubTests
{
    [TestClass]
    public class SerializationTests
    {
        private TestContext testContextInstance;

        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [ClassInitialize]
        public static void ClassSetup(TestContext tc)
        {
            Repository.Initialize();
        }

        private MessageSerializer Serialize()
        {
            MessageSerializer serializer = new MessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024) );
            serializer.AppendField("abc");
            serializer.AppendField((string)null);
            serializer.AppendField("1");
            serializer.AppendField("23");
            serializer.AppendTuple("Name", "Value");
            serializer.AppendTuple("Name1", "Value");
            serializer.AppendTuple("Name2", "Value");
            serializer.AppendTuple("Name3", "Value");
            serializer.AppendTuple("Name4", "Value");
            serializer.AppendTuple("Name5", "Value");
            serializer.AppendTuple("Name6", "Value1", "Value2");
            serializer.AppendTuple((string)null, null);
            serializer.AppendTuple("Name", null);
            return serializer;
        }




        [TestMethod]
        public void SerializationPerformance()
        {
            for (int index = 0; index < 100; index++)
            {
                Serialize();
            }
            Stopwatch watch = Stopwatch.StartNew();
            int iterations = 1000000;
            for (int index = 0; index < iterations; index++)
            {
                Serialize();
            }
            watch.Stop();
            this.TestContext.WriteLine("{0:n} serializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} serializations in 1 second", (double)iterations/(double)watch.ElapsedMilliseconds * 1000.00);
        }


        [TestMethod]
        public void ByteSerializationPerformance()
        {
            byte[] _abc = ASCIIEncoding.ASCII.GetBytes("abc");
            byte[] _1 = ASCIIEncoding.ASCII.GetBytes("1");
            byte[] _23 = ASCIIEncoding.ASCII.GetBytes("23");
            byte[] _Name = ASCIIEncoding.ASCII.GetBytes("Name");
            byte[] _Value = ASCIIEncoding.ASCII.GetBytes("Value");
            byte[] _Name1 = ASCIIEncoding.ASCII.GetBytes("Name1");
            byte[] _Name2 = ASCIIEncoding.ASCII.GetBytes("Name2");
            byte[] _Name3 = ASCIIEncoding.ASCII.GetBytes("Name3");
            byte[] _Name4 = ASCIIEncoding.ASCII.GetBytes("Name4");
            byte[] _Name5 = ASCIIEncoding.ASCII.GetBytes("Name5");
            byte[] _Name6 = ASCIIEncoding.ASCII.GetBytes("Name6");
            

            for (int index = 0; index < 100; index++)
            {
                MessageSerializer serializer = new MessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024));
                serializer.AppendField(_abc);
                serializer.AppendField((byte[])null);
                serializer.AppendField(_1);
                serializer.AppendField(_23);
                serializer.AppendTuple(_Name, _Value);
                serializer.AppendTuple(_Name1, _Value);
                serializer.AppendTuple(_Name2, _Value);
                serializer.AppendTuple(_Name3, _Value);
                serializer.AppendTuple(_Name4, _Value);
                serializer.AppendTuple(_Name5, _Value);
                serializer.AppendTuple(_Name6, _Value, _Value);
                serializer.AppendTuple((byte[])null, null);
                serializer.AppendTuple(_Name, null);
            }
            Stopwatch watch = Stopwatch.StartNew();
            int iterations = 1000000;
            for (int index = 0; index < iterations; index++)
            {
                MessageSerializer serializer = new MessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024));
                serializer.AppendField(_abc);
                serializer.AppendField((byte[])null);
                serializer.AppendField(_1);
                serializer.AppendField(_23);
                serializer.AppendTuple(_Name, _Value);
                serializer.AppendTuple(_Name1, _Value);
                serializer.AppendTuple(_Name2, _Value);
                serializer.AppendTuple(_Name3, _Value);
                serializer.AppendTuple(_Name4, _Value);
                serializer.AppendTuple(_Name5, _Value);
                serializer.AppendTuple(_Name6, _Value, _Value);
                serializer.AppendTuple((byte[])null, null);
                serializer.AppendTuple(_Name, null);
            }
            watch.Stop();
            this.TestContext.WriteLine("{0:n} serializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} serializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }

        [TestMethod]
        public void BasicDeserialization()
        {
            byte[] serialized = Serialize().GetBytes();
            MessageDeserializer deserializer = new MessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length));

            PubSubMessageType msgType = deserializer.GetMessageType();
            Assert.AreEqual<PubSubMessageType>(msgType, PubSubMessageType.DATA_MESSAGE);

            Assert.AreEqual<string>(deserializer.GetField(), "abc");
            Assert.AreEqual<string>(deserializer.GetField(), null);
            Assert.AreEqual<string>(deserializer.GetField(), "1");
            Assert.AreEqual<string>(deserializer.GetField(), "23");

            string name;
            string value;

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name");
            Assert.AreEqual<string>(value, "Value");

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name1");
            Assert.AreEqual<string>(value, "Value");

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name2");
            Assert.AreEqual<string>(value, "Value");

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name3");
            Assert.AreEqual<string>(value, "Value");

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name4");
            Assert.AreEqual<string>(value, "Value");

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name5");
            Assert.AreEqual<string>(value, "Value");

            string value2;
            deserializer.GetTuple(out name, out value, out value2);
            Assert.AreEqual<string>(name, "Name6");
            Assert.AreEqual<string>(value, "Value1");
            Assert.AreEqual<string>(value2, "Value2");

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, null);
            Assert.AreEqual<string>(value, null);

            deserializer.GetTuple(out name, out value);
            Assert.AreEqual<string>(name, "Name");
            Assert.AreEqual<string>(value, null);


            Assert.AreEqual<bool>(deserializer.HasMore(), false);
        }

        private static void Deserialization(byte[] serialized)
        {
            MessageDeserializer deserializer = new MessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length));
            string name;
            string value;
            string value2;

            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value);
            deserializer.GetTuple(out name, out value, out value2);
        }


        public MessageSerializer ByteSerialization()
        {
            byte[] _abc = ASCIIEncoding.ASCII.GetBytes("abc");
            byte[] _1 = ASCIIEncoding.ASCII.GetBytes("1");
            byte[] _23 = ASCIIEncoding.ASCII.GetBytes("23");
            byte[] _Name = ASCIIEncoding.ASCII.GetBytes("Name");
            byte[] _Value = ASCIIEncoding.ASCII.GetBytes("Value");
            byte[] _Name1 = ASCIIEncoding.ASCII.GetBytes("Name1");
            byte[] _Name2 = ASCIIEncoding.ASCII.GetBytes("Name2");
            byte[] _Name3 = ASCIIEncoding.ASCII.GetBytes("Name3");
            byte[] _Name4 = ASCIIEncoding.ASCII.GetBytes("Name4");
            byte[] _Name5 = ASCIIEncoding.ASCII.GetBytes("Name5");
            byte[] _Name6 = ASCIIEncoding.ASCII.GetBytes("Name6");

            MessageSerializer serializer = new MessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024));
            serializer.AppendField(_abc);
            serializer.AppendField((byte[])null);
            serializer.AppendField(_1);
            serializer.AppendField(_23);
            serializer.AppendTuple(_Name, _Value);
            serializer.AppendTuple(_Name1, _Value);
            serializer.AppendTuple(_Name2, _Value);
            serializer.AppendTuple(_Name3, _Value);
            serializer.AppendTuple(_Name4, _Value);
            serializer.AppendTuple(_Name5, _Value);
            serializer.AppendTuple(_Name6, _Value, _Value);
            serializer.AppendTuple((byte[])null, null);
            serializer.AppendTuple(_Name, null);
            return serializer;
            
        }

        private static void ByteDeserialization(byte[] serialized)
        {
            MessageDeserializer deserializer = new MessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length));
            ByteBuffer name;
            ByteBuffer value;
            ByteBuffer value2;

            deserializer.GetByteField();
            deserializer.GetByteField();
            deserializer.GetByteField();
            deserializer.GetByteField();
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value);
            deserializer.GetByteTuple(out name, out value, out value2);
        }

        [TestMethod]
        public void DeserializationPerformance()
        {
            byte[] serialized = Serialize().GetBytes();
            int iterations = 1000000;
            Stopwatch watch = Stopwatch.StartNew();
            for(int index=0; index < iterations; index++)
                Deserialization(serialized);
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations/(double)watch.ElapsedMilliseconds * 1000.00);
        }



        [TestMethod]
        public void ByteDeserializationPerformance()
        {
            byte[] serialized = ByteSerialization().GetBytes();
            int iterations = 1000000;
            Stopwatch watch = Stopwatch.StartNew();
            for (int index = 0; index < iterations; index++)
                ByteDeserialization(serialized);
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }



        [TestMethod]
        public void FullDeserializationPerformance()
        {
            DataMessage message = new DataMessage(SchemaCollection.AllSchemas["TOPIC1"]);
            message.AddData("00001", (1).ToString());
            message.AddData("00002", "00000002");
            message.AddData("00003", "00000003");
            message.AddData("00004", "00000004");
            message.AddData("00005", "00000005");
            message.AddData("00006", "00000006");
            message.AddData("00007", "00000007");
            message.AddData("00008", "00000008");
            message.AddData("00009", "00000009");
            message.AddData("00010", "00000010");
            ByteBuffer buffer = new ByteBuffer();
            message.Serialize(buffer);
            PubSubMessageFactory factory = new PubSubMessageFactory();
            int iterations = 1000000;
            Stopwatch watch = Stopwatch.StartNew();
            for (int index = 0; index < iterations; index++)
                factory.CreateMessage(buffer);
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }


        [TestMethod]
        public void FullDeserializationInternalPerformance()
        {
            DataMessage message = new DataMessage(SchemaCollection.AllSchemas["TOPIC1"]);
            message.AddData("00001", (1).ToString());
            message.AddData("00002", "00000002");
            message.AddData("00003", "00000003");
            message.AddData("00004", "00000004");
            message.AddData("00005", "00000005");
            message.AddData("00006", "00000006");
            message.AddData("00007", "00000007");
            message.AddData("00008", "00000008");
            message.AddData("00009", "00000009");
            message.AddData("00010", "00000010");
            ByteBuffer buffer = new ByteBuffer();
            message.Serialize(buffer);
            PubSubMessageFactoryInternal factory = new PubSubMessageFactoryInternal();
            int iterations = 1000000;
            Stopwatch watch = Stopwatch.StartNew();
            for (int index = 0; index < iterations; index++)
                factory.CreateMessage(buffer);
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }


        //FIX SERIALIZATION ////////////////////////////////////        
        private static MessageSerializer FixSerialize()
        {
            MessageSerializer serializer = new MessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024));
            serializer.AppendFixField("abc");
            serializer.AppendFixField((string)null);
            serializer.AppendFixField("1");
            serializer.AppendFixField("23");
            serializer.AppendFixTuple(1, "Value");
            serializer.AppendFixTuple(2, "Value");
            serializer.AppendFixTuple(3, "Value");
            serializer.AppendFixTuple(4, "Value");
            serializer.AppendFixTuple(5, "Value");
            serializer.AppendFixTuple(6, "Value");
            serializer.AppendFixTuple("7", "Value1", "Value2");
            serializer.AppendFixTuple(8, null);
            serializer.AppendFixTuple(9, null);
            return serializer;
        }


        [TestMethod]
        public void FixSerializationDeserialization()
        {
            byte[] serialized = FixSerialize().GetBytes();
            MessageDeserializer deserializer = new MessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length), 1);
            int index;
            ByteBuffer value0;
            ByteBuffer value;
            ByteBuffer value2;

            Assert.AreEqual<int>(3, deserializer.GetFixField().Length);
            Assert.AreEqual<int>(0, deserializer.GetFixField().Length);
            Assert.AreEqual<int>(1, deserializer.GetFixField().Length);
            Assert.AreEqual<int>(2, deserializer.GetFixField().Length);
            
            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(1, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(2, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(3, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(4, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(5, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(6, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetFixTuple(out value0, out value, out value2);
            Assert.AreEqual<int>(1, value0.Length);
            Assert.AreEqual<int>(6, value.Length);
            Assert.AreEqual<int>(6, value2.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(8, index);
            Assert.AreEqual<int>(0, value.Length);

            deserializer.GetFixTuple(out index, out value);
            Assert.AreEqual<int>(9, index);
            Assert.AreEqual<int>(0, value.Length);
        }


        [TestMethod]
        public  void FixSerializationPerformance()
        {
            for (int index = 0; index < 100; index++)
            {
                FixSerialize();
            }
            Stopwatch watch = Stopwatch.StartNew();
            int iterations = 1000000;
            for (int index = 0; index < iterations; index++)
            {
                FixSerialize();
            }
            watch.Stop();
            this.TestContext.WriteLine("{0:n} serializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} serializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }


        private static void FixDeserialization(byte[] serialized)
        {
            MessageDeserializer deserializer = new MessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length),1);
            int name;
            ByteBuffer value0;
            ByteBuffer value;
            ByteBuffer value2;

            deserializer.GetFixField();
            deserializer.GetFixField();
            deserializer.GetFixField();
            deserializer.GetFixField();
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out value0, out value, out value2);
            deserializer.GetFixTuple(out name, out value);
            deserializer.GetFixTuple(out name, out value);
        }

        [TestMethod]
        public void FixDeserializationPerformance()
        {
            byte[] serialized = FixSerialize().GetBytes();
            int iterations = 1000000;
            Stopwatch watch = Stopwatch.StartNew();
            for (int index = 0; index < iterations; index++)
                FixDeserialization(serialized);
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }



        //string serializaiton / buffer deserialization
        private static StringMessageSerializer StringSerialize()
        {
            StringMessageSerializer serializer = new StringMessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024));
            serializer.AppendField("abc");
            serializer.AppendField((string)null);
            serializer.AppendField("1");
            serializer.AppendField("23");
            serializer.AppendTuple(1, "Value");
            serializer.AppendTuple(2, "Value");
            serializer.AppendTuple(3, "Value");
            serializer.AppendTuple(4, "Value");
            serializer.AppendTuple(5, "Value");
            serializer.AppendTuple(6, "Value");
            serializer.AppendTuple("7", "Value1", "Value2");
            serializer.AppendTuple(8, null);
            serializer.AppendTuple(9, null);
            return serializer;
        }


        [TestMethod]
        public void ByteBufferDeserialization()
        {
            byte[] serialized = StringSerialize().GetBytes();
            ByteBufferMessageDeserializer deserializer = new ByteBufferMessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length), 1);
            int index;
            ByteBuffer value0;
            ByteBuffer value;
            ByteBuffer value2;

            Assert.AreEqual<int>(3, deserializer.GetField().Length);
            Assert.AreEqual<int>(0, deserializer.GetField().Length);
            Assert.AreEqual<int>(1, deserializer.GetField().Length);
            Assert.AreEqual<int>(2, deserializer.GetField().Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(1, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(2, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(3, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(4, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(5, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(6, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out value0, out value, out value2);
            Assert.AreEqual<int>(1, value0.Length);
            Assert.AreEqual<int>(6, value.Length);
            Assert.AreEqual<int>(6, value2.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(8, index);
            Assert.AreEqual<int>(0, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(9, index);
            Assert.AreEqual<int>(0, value.Length);
        }



       
        public void ByteBufferDeserialization(byte[] serialized)
        {   
            ByteBufferMessageDeserializer deserializer = new ByteBufferMessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length), 1);
            int index;
            ByteBuffer value0;
            ByteBuffer value;
            ByteBuffer value2;

            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetField();

            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out value0, out value, out value2);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
        }

        [TestMethod]
        public void ByteBufferDeserializationPerformance()
        {
            byte[] serialized = StringSerialize().GetBytes();
            int iterations = 0;
            Stopwatch watch = Stopwatch.StartNew();
            while (iterations < 1000000)
            {
                ByteBufferDeserialization(serialized);
                iterations++;
            }
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }






        //buffer serializaiton / string deserialization
        private static ByteBufferMessageSerializer ByteBufferSerialize()
        {
            ByteBufferMessageSerializer serializer = new ByteBufferMessageSerializer(PubSubMessageType.DATA_MESSAGE, new ByteBuffer(1024));
            serializer.AppendField("abc");
            serializer.AppendField((string)null);
            serializer.AppendField("1");
            serializer.AppendField("23");
            serializer.AppendTuple(1, ByteBuffer.StringToByteBuffer("Value"));
            serializer.AppendTuple(2, ByteBuffer.StringToByteBuffer("Value"));
            serializer.AppendTuple(3, ByteBuffer.StringToByteBuffer("Value"));
            serializer.AppendTuple(4, ByteBuffer.StringToByteBuffer("Value"));
            serializer.AppendTuple(5, ByteBuffer.StringToByteBuffer("Value"));
            serializer.AppendTuple(6, ByteBuffer.StringToByteBuffer("Value"));
            serializer.AppendTuple(ByteBuffer.StringToByteBuffer("7"), ByteBuffer.StringToByteBuffer("Value1"), ByteBuffer.StringToByteBuffer("Value2"));
            serializer.AppendTuple(8, null);
            serializer.AppendTuple(9, null);
            return serializer;
        }


        [TestMethod]
        public void StringDeserialization()
        {
            byte[] serialized = ByteBufferSerialize().GetBytes();
            StringMessageDeserializer deserializer = new StringMessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length), 1);
            int index;
            string value0;
            string value;
            string value2;

            Assert.AreEqual<int>(3, deserializer.GetField().Length);
            Assert.AreEqual<int>(0, deserializer.GetField().Length);
            Assert.AreEqual<int>(1, deserializer.GetField().Length);
            Assert.AreEqual<int>(2, deserializer.GetField().Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(1, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(2, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(3, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(4, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(5, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(6, index);
            Assert.AreEqual<int>(5, value.Length);

            deserializer.GetTuple(out value0, out value, out value2);
            Assert.AreEqual<int>(1, value0.Length);
            Assert.AreEqual<int>(6, value.Length);
            Assert.AreEqual<int>(6, value2.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(8, index);
            Assert.AreEqual<int>(0, value.Length);

            deserializer.GetTuple(out index, out value);
            Assert.AreEqual<int>(9, index);
            Assert.AreEqual<int>(0, value.Length);
        }


        public void StringDeserialization(byte[] serialized)
        {
            StringMessageDeserializer deserializer = new StringMessageDeserializer(new ByteBuffer(serialized, 0, serialized.Length, serialized.Length), 1);
            int index;
            string value0;
            string value;
            string value2;

            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetField();
            deserializer.GetField();

            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out value0, out value, out value2);
            deserializer.GetTuple(out index, out value);
            deserializer.GetTuple(out index, out value);
        }

        [TestMethod]
        public void StringDeserializationPerformance()
        {
            byte[] serialized = ByteBufferSerialize().GetBytes();
            int iterations = 0;
            Stopwatch watch = Stopwatch.StartNew();
            while (iterations < 1000000)
            {
                StringDeserialization(serialized);
                iterations++;
            }
            watch.Stop();
            this.TestContext.WriteLine("{0:n} deserializations in {1}ms", iterations, watch.ElapsedMilliseconds);
            this.TestContext.WriteLine("{0:n} deserializations in 1 second", (double)iterations / (double)watch.ElapsedMilliseconds * 1000.00);
        }
        
    }
}

